﻿using System;
using System.Collections.Specialized;
using System.Linq;
using Loki.Engine;
using Loki.Model;
using NUnit.Framework;

namespace Loki.Core.Model.Test
{
    [TestFixture]
    public class EntityContainerTest : AssertionHelper
    {
        DummyLoader _Loader;
        EntityContainer<DummyEntity, Guid> _Container;



        [SetUp]
        public void SetUp()
        {
            _Loader = new DummyLoader();
            ContainerConfiguration<DummyEntity, Guid> L_Config = new ContainerConfiguration<DummyEntity, Guid>()
            {
                LoadingErrorCode = "000",
                PrimaryKey = new UniqueKeyConfiguration<DummyEntity, Guid>() { Indexer = x => x.ID, Loader = x => _Loader.Get(x), Default = x => DummyLoader.Empty(x) },
                Indexes = new IIndexConfiguration<DummyEntity>[]{
                                new IndexConfiguration<DummyEntity, int>(){ Indexer = x=>x.Key1, Loader = x=>_Loader.GetAllByKey1((int)x)},
                                new IndexConfiguration<DummyEntity, string>(){Indexer = x=>x.Key2}
                },
                FullLoader = () => _Loader.GetAll(),
                PreUpdate = (x) => _Loader.PreUpdate(x),
                PostUpdate = (x) => _Loader.PostUpdate(x),
            };
            _Container = new EntityContainer<DummyEntity, Guid>(L_Config);
        }

        void _Container_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {

        }

        [Test]
        public void TestFullLoadResetEvent()
        {
            bool L_IsResetEvent = false;
            _Container.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e)
            {
                L_IsResetEvent = e.Action == NotifyCollectionChangedAction.Reset;
            };
            int L_Count = _Container.Count();
            Expect(L_IsResetEvent,
                Is.True);
        }

        [Test]
        public void TestRegisterAddEvent()
        {
            bool L_IsAddEvent = false;
            _Container.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e)
            {
                L_IsAddEvent = e.Action == NotifyCollectionChangedAction.Add && e.NewItems[0] == _Loader.NotStored;
            };
            _Container.Register(_Loader.NotStored);
            Expect(L_IsAddEvent,
                Is.True);
        }

        [Test]
        public void TestRegisterReplaceEvent()
        {
            bool L_IsAddEvent = false;
            _Container.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e)
            {
                L_IsAddEvent = e.Action == NotifyCollectionChangedAction.Replace && e.NewItems[0] == _Loader.Store[0] && e.OldItems[0] == _Loader.Store[0];
            };
            _Container.Count();
            _Container.Register(_Loader.Store[0]);
            Expect(L_IsAddEvent,
                Is.True);
        }

        [Test]
        public void TestFullLoad()
        {
            int L_Count = _Container.Count();
            Expect(_Loader.LoadAll,
                Is.EqualTo(1));
        }

        [Test]
        public void TestFullLoadOnce()
        {
            int L_Count = _Container.Count();
            int L_Count2 = _Container.Count();

            Expect(_Loader.LoadAll,
                Is.EqualTo(1));
            Expect(L_Count,
                Is.EqualTo(L_Count2));
        }

        [Test]
        public void TestFullLoadResetOnce()
        {
            int i = 0;
            _Container.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e)
            {
                i++;
            };
            _Container.Count();
            _Container.Count();
            Expect(i,
                Is.EqualTo(1));
        }

        [Test]
        public void TestGet()
        {
            DummyEntity L_Item = _Container[_Loader.Store[0].ID];

            Expect(L_Item.ID,
                Is.EqualTo(_Loader.Store[0].ID));
            Expect(_Loader.LoadedPKAsks[L_Item.ID],
                Is.EqualTo(1));
            Expect(_Loader.LoadAll,
                Is.EqualTo(0));
        }

        [Test]
        public void TestGetAllBy()
        {
            int L_Count = _Container.GetAllBy("Key1", 1).Count();

            Expect(L_Count,
                Is.EqualTo(2));
            Expect(_Loader.LoadedKey1Asks[1],
                Is.EqualTo(1));
            Expect(_Loader.LoadAll,
                Is.EqualTo(0));
        }

        [Test]
        public void TestRemoveEvent()
        {
            // load all
            _Container.Count();
            bool L_Validate = false;

            _Container.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e)
            {
                L_Validate = e.Action == NotifyCollectionChangedAction.Remove && e.OldItems[0] == _Loader.Store[0];
            };

            _Container.Remove(_Loader.Store[0]);

            Expect(L_Validate,
                Is.True);
        }

        [Test]
        public void TestRemoveAndGet()
        {
            // load all
            _Container.Count();
            Guid L_PK = _Loader.Store[0].ID;

            _Container.Remove(_Loader.Store[0]);
            _Container.Get(L_PK);

            Expect(_Loader.LoadedPKAsks[L_PK],
                Is.EqualTo(1));
        }
    }
}
